/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
/*
 * This copy of Woodstox XML processor is licensed under the
 * Apache (Software) License, version 2.0 ("the License").
 * See the License for details about distribution rights, and the
 * specific rights regarding derivate works.
 *
 * You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/
 *
 * A copy is also included in the downloadable source code package
 * containing Woodstox, in file "ASL2.0", under the same directory
 * as this file.
 */
package com.je.bpm.core.json.converter.json.converter;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.je.bpm.core.model.BaseElement;
import com.je.bpm.core.model.button.Button;
import com.je.bpm.core.model.button.TaskButton;
import com.je.bpm.core.model.button.TaskCommitBreakdownButton;
import com.je.bpm.core.model.button.TaskDismissBreakdownButton;
import com.je.bpm.core.model.config.CustomEvent;
import com.je.bpm.core.model.config.task.*;
import com.je.bpm.core.model.task.KaiteBaseUserTask;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 凯特用户任务基础json解析器
 */
public abstract class AbstractKaiteBaseUserTaskJsonConverter extends AbstractKaiteTaskJsonConverter {

    @Override
    protected void convertElementToJson(ObjectNode propertiesNode, BaseElement baseElement, ObjectNode flowElementNode) {
        KaiteBaseUserTask userTask = (KaiteBaseUserTask) baseElement;
        propertiesNode.put(PROPERTY_USERTASK_CATEGORY, userTask.getCategory());
        propertiesNode.put(PROPERTY_OVERRIDE_ID, userTask.getId());
        propertiesNode.put(PROPERTY_NAME, userTask.getName());
        TaskBasicConfigImpl taskBasicConfig = userTask.getTaskBasicConfig();
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_FORMSCHEMENAME, taskBasicConfig.getFormSchemeName());
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_FORMSCHEMEID, taskBasicConfig.getFormSchemeId());
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_LISTSYNCHRONIZATION, convertBooleanToIntJson(taskBasicConfig.getListSynchronization()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_RETRIEVE, convertBooleanToIntJson(taskBasicConfig.getRetrieve()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_URGE, convertBooleanToIntJson(taskBasicConfig.getUrge()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_INVALID, convertBooleanToIntJson(taskBasicConfig.getInvalid()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_DELEGATE, convertBooleanToIntJson(taskBasicConfig.getDelegate()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_TRANSFER, convertBooleanToIntJson(taskBasicConfig.getTransfer()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_FORMEDITABLE, convertBooleanToIntJson(taskBasicConfig.getFormEditable()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_REMIND, convertBooleanToIntJson(taskBasicConfig.getRemind()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_SIMPLEAPPROVAL, convertBooleanToIntJson(taskBasicConfig.getSimpleApproval()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_SELECTALL, convertBooleanToIntJson(taskBasicConfig.getSelectAll()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_ASYNTREE, convertBooleanToIntJson(taskBasicConfig.getAsynTree()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_JUMP, convertBooleanToIntJson(taskBasicConfig.getJump()));
        propertiesNode.put(PROPERTY_TASK_PROPERTIES_LOGICALJUDGMENT, convertBooleanToIntJson(taskBasicConfig.getLogicalJudgment()));
        propertiesNode.put(PROPERTY_COUNTERSIGNED_SEQUENTIAL, convertBooleanToIntJson(taskBasicConfig.getSequential()));
        propertiesNode.put(SECURITY_ENABLE, convertBooleanToIntJson(taskBasicConfig.getSecurityEnable()));
        propertiesNode.put(SECURITY_CODE, taskBasicConfig.getSecurityCode());
        propertiesNode.put(COUNTERSIGN, taskBasicConfig.getCountersign());
        propertiesNode.put(SIGN_BACK, taskBasicConfig.getSignBack());
        propertiesNode.put(FORCED_SIGNATURE_BACK, taskBasicConfig.getForcedSignatureBack());
        propertiesNode.put(STAGING, taskBasicConfig.getStaging());
        propertiesNode.put(BASIC_RUNTIME_TUNING, taskBasicConfig.getBasicRuntimeTuning());
        propertiesNode.put(PROPERTY_PROCESS_INITIATOR_CANURGED, taskBasicConfig.isInitiatorCanUrged());
        propertiesNode.put(PROPERTY_PROCESS_INITIATOR_CANINVALID, taskBasicConfig.isInitiatorCanInvalid());
        propertiesNode.put(PROPERTY_PROCESS_INITIATOR_CANCANCEL, taskBasicConfig.isInitiatorCanCancel());
        //提交分解
        parseCommitBreakdownConfigToJson(userTask, flowElementNode);
        //驳回配置
        parseDismissConfigToJson(userTask, flowElementNode);
        //预警与延期
        parseEarlyWarningAndPostponementConfigToJson(userTask, flowElementNode);
        //传阅
        parseTaskPassRoundConfigToJson(userTask, flowElementNode);
        //按钮
        fillUserTaskButtonConfigToJson(userTask, flowElementNode);
        //事件
        parseCustomEventListenersConfigToJson(userTask.getCustomEventListeners(), flowElementNode);
        //加签
        addSignatureTaskConfigToJson(userTask, flowElementNode);
        //审批公告
        approvalNoticeTaskConfigToJson(userTask, flowElementNode);
        //表单控制
        formConfigTaskConfigToJson(userTask, flowElementNode);
        setPropertyValue(PROPERTY_USERTASK_DUEDATE, userTask.getDueDate(), propertiesNode);
        super.convertElementToJson(propertiesNode, baseElement);
    }


    /**
     * 表单控制
     *
     * @return Void
     */
    protected void formConfigTaskConfigToJson(KaiteBaseUserTask userTask, ObjectNode flowElementNode) {
        ObjectNode formConfig = objectMapper.createObjectNode();

        TaskFormBasicConfigImpl taskFormBasicConfig = userTask.getTaskFormBasicConfig();
        ObjectNode fieldAssignment = objectMapper.createObjectNode();
        Map<String, String> taskFormFieldSetValueConfig = taskFormBasicConfig.getTaskFormFieldSetValueConfig();
        taskFormFieldSetValueConfig.keySet().forEach(key -> fieldAssignment.put(key, taskFormFieldSetValueConfig.get(key)));
        formConfig.set(PROPERTY_USERTASK_FORM_FIELD_ASSIGNMENT_CONFIG, fieldAssignment);

        ObjectNode fieldControl = objectMapper.createObjectNode();
        TaskFormFieldConfigImpl taskFormFieldConfig = taskFormBasicConfig.getTaskFormFieldConfig();
        List<TaskFormFieldConfigImpl.FormFieldConfig> formFields = taskFormFieldConfig.getFormFields();
        for (TaskFormFieldConfigImpl.FormFieldConfig formFieldConfig : formFields) {
            ObjectNode fieldConfig = objectMapper.createObjectNode();
            fieldConfig.put(PROPERTY_USERTASK_FORM_BASIC_EDITABLE, convertBooleanToIntJson(formFieldConfig.getEditable()));
            fieldConfig.put(PROPERTY_USERTASK_FORM_FORMFIELD_READONLY, convertBooleanToIntJson(formFieldConfig.getReadonly()));
            fieldConfig.put(PROPERTY_USERTASK_FORM_FORMFIELD_HIDDEN, convertBooleanToIntJson(formFieldConfig.getHidden()));
            fieldConfig.put(PROPERTY_USERTASK_FORM_FORMFIELD_DISPLAY, convertBooleanToIntJson(formFieldConfig.getDisplay()));
            fieldConfig.put(PROPERTY_USERTASK_FORM_FORMFIELD_REQUIRED, convertBooleanToIntJson(formFieldConfig.getRequired()));
            fieldControl.set(formFieldConfig.getCode(), fieldConfig);
        }
        formConfig.set(PROPERTY_USERTASK_FORM_FIELD_CONTROL_CONFIG, fieldControl);

        ObjectNode taskFormButton = objectMapper.createObjectNode();
        TaskFormButtonConfigImpl taskFormButtonConfig = taskFormBasicConfig.getTaskFormButtonConfig();
        List<TaskFormButtonConfigImpl.ButtonConfig> buttonConfigs = taskFormButtonConfig.getButtonConfigs();
        for (TaskFormButtonConfigImpl.ButtonConfig buttonConfig : buttonConfigs) {
            ObjectNode buttonNode = objectMapper.createObjectNode();
            buttonNode.put(UNIVERSAL_ENABLE, convertBooleanToIntJson(buttonConfig.getEnable()));
            taskFormButton.set(buttonConfig.getCode(), buttonNode);
        }
        formConfig.set(PROPERTY_USERTASK_FORM_TASKFORMBUTTON_CONFIG, taskFormButton);

        ObjectNode taskChildFunc = objectMapper.createObjectNode();
        TaskFormChildFuncConfigImpl taskFormChildFuncConfig = taskFormBasicConfig.getTaskFormChildFuncConfig();
        List<TaskFormChildFuncConfigImpl.ChildFuncConfig> childFuncConfigs = taskFormChildFuncConfig.getChildFuncConfigs();
        for (TaskFormChildFuncConfigImpl.ChildFuncConfig childFuncConfig : childFuncConfigs) {
            ObjectNode childFuncNode = objectMapper.createObjectNode();
            childFuncNode.put(PROPERTY_USERTASK_FORM_BASIC_EDITABLE, convertBooleanToIntJson(childFuncConfig.getEditable()));
            childFuncNode.put(PROPERTY_USERTASK_FORM_CHILDFUNC_HIDDEN, convertBooleanToIntJson(childFuncConfig.getHidden()));
            childFuncNode.put(PROPERTY_USERTASK_FORM_CHILDFUNC_DISPLAY, convertBooleanToIntJson(childFuncConfig.getDisplay()));
            taskChildFunc.set(childFuncConfig.getCode(), childFuncNode);
        }
        formConfig.set(PROPERTY_USERTASK_FORM_TASKCHILDFUNC_CONFIG, taskChildFunc);

        flowElementNode.set(PROPERTY_USERTASK_FORM_CONFIG, formConfig);
    }

    /**
     * 审批公告
     */
    protected void approvalNoticeTaskConfigToJson(KaiteBaseUserTask userTask, ObjectNode flowElementNode) {
        ObjectNode approvalNotice = objectMapper.createObjectNode();
        TaskApprovalNoticeConfigImpl approvalNoticeConfig = userTask.getTaskApprovalNoticeConfig();
        if (approvalNoticeConfig == null) {
            return;
        }
        approvalNotice.put(PROPERTY_TASK_APPROVALNOTICE_PROCESSINITIATOR, convertBooleanToIntJson(approvalNoticeConfig.isStartUser()));
        approvalNotice.put(PROPERTY_TASK_APPROVALNOTICE_THISNODEAPPROVED, convertBooleanToIntJson(approvalNoticeConfig.isApprovedPerson()));
        approvalNotice.put(PROPERTY_TASK_APPROVALNOTICE_THISNODEAPPROVALDIRECTLYUNDERLEADER, convertBooleanToIntJson(approvalNoticeConfig.isApproverDirectLeader()));
        approvalNotice.put(PROPERTY_TASK_APPROVALNOTICE_THISNODEAPPROVALDEPTLEADER, convertBooleanToIntJson(approvalNoticeConfig.isApproverDeptLeader()));
        flowElementNode.set(PROPERTY_TASK_APPROVALNOTICE_CONFIG, approvalNotice);
    }

    /**
     * 审批公告
     *
     * @param elementNode node
     * @param userTask    task
     */
    private void parseJsonToTaskApprovalNoticeConfig(JsonNode elementNode, KaiteBaseUserTask userTask) {
        TaskApprovalNoticeConfigImpl taskApprovalNoticeConfig = new TaskApprovalNoticeConfigImpl();
        JsonNode approvalConfig = elementNode.get(PROPERTY_TASK_APPROVALNOTICE_CONFIG);
        taskApprovalNoticeConfig.setStartUser(getValueAsBoolean(PROPERTY_TASK_APPROVALNOTICE_PROCESSINITIATOR, approvalConfig));
        taskApprovalNoticeConfig.setApprovedPerson(getValueAsBoolean(PROPERTY_TASK_APPROVALNOTICE_THISNODEAPPROVED, approvalConfig));
        taskApprovalNoticeConfig.setApproverDirectLeader(getValueAsBoolean(PROPERTY_TASK_APPROVALNOTICE_THISNODEAPPROVALDIRECTLYUNDERLEADER, approvalConfig));
        taskApprovalNoticeConfig.setApproverDeptLeader(getValueAsBoolean(PROPERTY_TASK_APPROVALNOTICE_THISNODEAPPROVALDEPTLEADER, approvalConfig));
        userTask.setTaskApprovalNoticeConfig(taskApprovalNoticeConfig);
    }

    /**
     * 加签配置
     */
    protected void addSignatureTaskConfigToJson(KaiteBaseUserTask userTask, ObjectNode flowElementNode) {
        ObjectNode taskPassroundNode = objectMapper.createObjectNode();
        AddSignatureConfigImpl addSignatureConfig = userTask.getAddSignatureConfig();
        taskPassroundNode.put(PROPERTY_ENABLE, convertBooleanToIntJson(addSignatureConfig.getEnable()));
        taskPassroundNode.put(PROPERTY_TASK_ADDSIGNATURE_UNLIMITED, convertBooleanToIntJson(addSignatureConfig.getUnlimited()));
        taskPassroundNode.put(PROPERTY_TASK_ADDSIGNATURE_NOT_COUNTERSIGNED, convertBooleanToIntJson(addSignatureConfig.getNotCountersigned()));
        taskPassroundNode.put(PROPERTY_TASK_ADDSIGNATURE_MANDATORY_COUNTERSIGNATURE, convertBooleanToIntJson(addSignatureConfig.getMandatoryCountersignature()));
        ArrayNode sourceArray = objectMapper.createArrayNode();
        List<PassRoundResource> list = addSignatureConfig.getCirculationRules();
        if (list.size() > 0) {
            for (PassRoundResource passRoundResource : list) {
                sourceArray.add(fillPassUserConfigToJson(passRoundResource));
            }
        }
        taskPassroundNode.set(PROPERTY_USERTASK_PASSROUND_CIRCULATIONRULES_CONFIG, sourceArray);
        flowElementNode.set(PROPERTY_TASK_ADDSIGNATURE_CONFIG, taskPassroundNode);
    }


    /**
     * 加签
     *
     * @param elementNode node
     * @param userTask    task
     */
    private void parseJsonToAddSignatureConfig(JsonNode elementNode, KaiteBaseUserTask userTask) {
        AddSignatureConfigImpl addSignatureConfig = new AddSignatureConfigImpl();
        JsonNode addConfig = elementNode.get(PROPERTY_TASK_ADDSIGNATURE_CONFIG);
        if (addConfig == null) {
            return;
        }
        addSignatureConfig.setEnable(getValueAsBoolean(UNIVERSAL_ENABLE, addConfig));
        addSignatureConfig.setUnlimited(getValueAsBoolean(PROPERTY_TASK_ADDSIGNATURE_UNLIMITED, addConfig));
        addSignatureConfig.setNotCountersigned(getValueAsBoolean(PROPERTY_TASK_ADDSIGNATURE_NOT_COUNTERSIGNED, addConfig));
        addSignatureConfig.setMandatoryCountersignature(getValueAsBoolean(PROPERTY_TASK_ADDSIGNATURE_MANDATORY_COUNTERSIGNATURE, addConfig));
        List<PassRoundResource> circulationRules = new ArrayList<>();
        ArrayNode circulationRulesNode = (ArrayNode) addConfig.get(PROPERTY_USERTASK_PASSROUND_CIRCULATIONRULES_CONFIG);
        for (JsonNode circulationRule : circulationRulesNode) {
            PassRoundResource passRoundResource = new PassRoundResource();
            passRoundResource.setPassRoundTypeEnum(PassRoundResource.PassRoundTypeEnum.getType(getValueAsString(PROPERTY_USERTASK_PASSROUND_CIRCULATIONRULES_CODE, circulationRule)));
            JsonNode config = circulationRule.get(UNIVERSAL_CONFIG);
            passRoundResource.setResourceId(getValueAsString(PASS_ROUND_ID, config));
            passRoundResource.setResourceName(getValueAsString(UNIVERSAL_NAME, config));
            passRoundResource.setService(getValueAsString(PROPERTY_ASSIGNMENT_CUSTOM_SERVICENAME, config));
            passRoundResource.setMethod(getValueAsString(PROPERTY_ASSIGNMENT_CUSTOM_METHODNAME, config));
            circulationRules.add(passRoundResource);
        }
        addSignatureConfig.setCirculationRules(circulationRules);
        userTask.setAddSignatureConfig(addSignatureConfig);
    }


    /**
     * 预警与延期
     */
    private void parseEarlyWarningAndPostponementConfigToJson(KaiteBaseUserTask userTask, ObjectNode flowElementNode) {
        ObjectNode earlyWarningAndPostponementNode = objectMapper.createObjectNode();
        if (userTask.getTaskEarlyWarningAndPostponementConfig() != null) {
            TaskEarlyWarningAndPostponementConfigImpl taskEarlyWarningAndPostponementConfig = userTask.getTaskEarlyWarningAndPostponementConfig();
            earlyWarningAndPostponementNode.put(UNIVERSAL_ENABLE, convertBooleanToIntJson(taskEarlyWarningAndPostponementConfig.isEnabled()));
            ArrayNode sourceArray = objectMapper.createArrayNode();
            for (EarlyWarningAndPostponementSource source : taskEarlyWarningAndPostponementConfig.getSource()) {
                ObjectNode eachNode = objectMapper.createObjectNode();
                eachNode.put(UNIVERSAL_NAME, source.getSourceType().getName());
                eachNode.put(UNIVERSAL_CODE, source.getSourceType().toString());
//                eachNode.put(PROPERTY_TASK_EARLYWARNINGANDPOSTPONEMENT_DURATION, source.getDuration());
//                eachNode.put(PROPERTY_TASK_EARLYWARNINGANDPOSTPONEMENT_UNITNAME, source.getHandlePeriodType().getName());
//                eachNode.put(PROPERTY_TASK_EARLYWARNINGANDPOSTPONEMENT_UNITCODE, source.getHandlePeriodType().toString());
//                eachNode.put(PROPERTY_TASK_EARLYWARNINGANDPOSTPONEMENT_SERVICEANDMETHOD, source.getCallbackServiceName());
                sourceArray.add(eachNode);
            }
            earlyWarningAndPostponementNode.set(UNIVERSAL_RESOURCE, sourceArray);
        }
        flowElementNode.set(PROPERTY_TASK_EARLYWARNINGANDPOSTPONEMENT_CONFIG, earlyWarningAndPostponementNode);
    }

    /**
     * 预警与延期
     *
     * @param elementNode node
     * @param userTask    task
     */
    private void parseJsonToTaskEarlyWarningAndPostponementConfig(JsonNode elementNode, KaiteBaseUserTask userTask) {
        TaskEarlyWarningAndPostponementConfigImpl taskEarlyWarningAndPostponementConfig = new TaskEarlyWarningAndPostponementConfigImpl();
        JsonNode jsonNode = elementNode.get(PROPERTY_TASK_EARLYWARNINGANDPOSTPONEMENT_CONFIG);
        taskEarlyWarningAndPostponementConfig.setEnabled(getValueAsBoolean(UNIVERSAL_ENABLE, jsonNode));
        taskEarlyWarningAndPostponementConfig.setProcessingTimeLimitDuration(getValueAsString(PROCESSING_TIME_LIMIT_DURATION, jsonNode));
        taskEarlyWarningAndPostponementConfig.setProcessingTimeLimitUnitName(getValueAsString(PROCESSING_TIME_LIMIT_UNITNAME, jsonNode));
        taskEarlyWarningAndPostponementConfig.setProcessingTimeLimitUnitCode(getValueAsString(PROCESSING_TIME_LIMIT_UNITCODE, jsonNode));
        taskEarlyWarningAndPostponementConfig.setWarningTimeLimitDuration(getValueAsString(WARNING_TIME_LIMIT_DURATION, jsonNode));
        taskEarlyWarningAndPostponementConfig.setWarningTimeLimitUnitName(getValueAsString(WARNING_TIME_LIMIT_UNITNAME, jsonNode));
        taskEarlyWarningAndPostponementConfig.setWarningTimeLimitUnitCode(getValueAsString(WARNING_TIME_LIMIT_UNITCODE, jsonNode));
        taskEarlyWarningAndPostponementConfig.setReminderFrequencyDuration(getValueAsString(REMINDER_FREQUENCY_DURATION, jsonNode));
        taskEarlyWarningAndPostponementConfig.setReminderFrequencyUnitName(getValueAsString(REMINDER_FREQUENCY_UNITNAME, jsonNode));
        taskEarlyWarningAndPostponementConfig.setReminderFrequencyUnitCode(getValueAsString(REMINDER_FREQUENCY_UNITCODE, jsonNode));
        List<EarlyWarningAndPostponementSource> source = new ArrayList<>();
        ArrayNode arrayNode = (ArrayNode) jsonNode.get(UNIVERSAL_RESOURCE);
        for (JsonNode sourceJson : arrayNode) {
            EarlyWarningAndPostponementSource earlyWarningAndPostponementSource = new EarlyWarningAndPostponementSource();
            earlyWarningAndPostponementSource.setExecutionType(EarlyWarningAndPostponementSource.ExecutionTypeEnum.getType(getValueAsString(UNIVERSAL_TYPE, sourceJson)));
            earlyWarningAndPostponementSource.setService(getValueAsString(PROPERTY_ASSIGNMENT_CUSTOM_SERVICENAME, sourceJson));
            earlyWarningAndPostponementSource.setMethod(getValueAsString(PROPERTY_ASSIGNMENT_CUSTOM_METHODNAME, sourceJson));
            source.add(earlyWarningAndPostponementSource);
        }
        taskEarlyWarningAndPostponementConfig.setSource(source);
        userTask.setTaskEarlyWarningAndPostponementConfig(taskEarlyWarningAndPostponementConfig);
    }

    /**
     * 提交分解json
     */
    private void parseCommitBreakdownConfigToJson(KaiteBaseUserTask userTask, ObjectNode flowElementNode) {
        List<TaskCommitBreakdownButton> list = userTask.getCommitBreakdownButtonList();
        ArrayNode userTaskCommentArray = objectMapper.createArrayNode();
        if (list.size() > 0) {
            for (TaskCommitBreakdownButton taskButton : list) {
                ObjectNode eachButtonNode = objectMapper.createObjectNode();
                eachButtonNode.put(PROPERTY_TASK_COMMIT_BREAKDOWN_BUTTON_NAME, taskButton.getName());
                eachButtonNode.put(PROPERTY_TASK_COMMIT_BREAKDOWN_NODE_ID, taskButton.getNodeId());
                eachButtonNode.put(PROPERTY_TASK_COMMIT_BREAKDOWN_NODE_NAME, taskButton.getName());
                userTaskCommentArray.add(eachButtonNode);
            }
        }
        flowElementNode.set(PROPERTY_TASK_COMMIT_BREAKDOWN_CONFIG, userTaskCommentArray);
    }

    /**
     * 提交分解
     *
     * @param elementNode node
     * @param userTask    task
     */
    private void parseJsonToCommitBreakdownButtonList(JsonNode elementNode, KaiteBaseUserTask userTask) {
        List<TaskCommitBreakdownButton> commitBreakdownButtonList = new ArrayList<>();
        if (elementNode.get(PROPERTY_TASK_COMMIT_BREAKDOWN_CONFIG) == null) {
            return;
        }
        if (!(elementNode.get(PROPERTY_TASK_COMMIT_BREAKDOWN_CONFIG) instanceof ArrayNode)) {
            return;
        }
        ArrayNode arrayNode = (ArrayNode) elementNode.get(PROPERTY_TASK_COMMIT_BREAKDOWN_CONFIG);
        if (arrayNode == null) {
            return;
        }
        for (JsonNode jsonNode : arrayNode) {
            TaskCommitBreakdownButton taskCommitBreakdownButton = new TaskCommitBreakdownButton();
            taskCommitBreakdownButton.setNodeName(getValueAsString(PROPERTY_BUTTON_NAME, jsonNode));
            taskCommitBreakdownButton.setNodeId(getValueAsString(PROPERTY_TASK_COMMIT_BREAKDOWN_NODE_ID, jsonNode));
            taskCommitBreakdownButton.setName(getValueAsString(PROPERTY_TASK_COMMIT_BREAKDOWN_NODE_NAME, jsonNode));
            commitBreakdownButtonList.add(taskCommitBreakdownButton);
        }
        userTask.setCommitBreakdownButtonList(commitBreakdownButtonList);
    }

    /**
     * 任务按钮
     *
     * @return void
     */
    protected void fillUserTaskButtonConfigToJson(KaiteBaseUserTask userTask, ObjectNode flowElementNode) {
        ArrayNode processButtonArrayNode = objectMapper.createArrayNode();
        List<TaskButton> buttons = userTask.getButtons().getButtons();
        ObjectNode eachNode;
        for (Button eachButton : buttons) {
            eachNode = objectMapper.createObjectNode();
            eachNode.put(PROPERTY_BUTTON_ID, eachButton.getId());
            eachNode.put(PROPERTY_BUTTON_CODE, eachButton.getCode());
            eachNode.put(PROPERTY_BUTTON_NAME, eachButton.getName());
            eachNode.put(PROPERTY_BUTTON_CUSTOMIZE_NAME, eachButton.getCustomizeName());
            eachNode.put(PROPERTY_BUTTON_CUSTOMIZE_COMMENTS, eachButton.getCustomizeComments());
            eachNode.put(PROPERTY_BUTTON_OPERATION, eachButton.getOperationId());
            eachNode.put(PROPERTY_BUTTON_BACKEND_LISTENERS, eachButton.getBackendListeners());
            eachNode.put(PROPERTY_BUTTON_APP_LISTENERS, eachButton.getAppListeners());
            eachNode.put(PROPERTY_BUTTON_PC_LISTENERS, eachButton.getPcListeners());
            eachNode.put(PROPERTY_TASK_BUTTON_DISLAY_EXPRESSION, eachButton.getDisplayExpressionWhenStarted());
            processButtonArrayNode.add(eachNode);
        }
        flowElementNode.set(PROPERTY_BUTTONS_CONFIG, processButtonArrayNode);
    }

    /**
     * 写入流程自定义事件
     *
     * @param customEventList 自定义事件list
     */
    public void parseCustomEventListenersConfigToJson(List<CustomEvent> customEventList, ObjectNode propertiesNode) {
        ArrayNode processCustomEventListArrayNode = objectMapper.createArrayNode();
        ObjectNode eachNode;
        for (CustomEvent customEvent : customEventList) {
            eachNode = objectMapper.createObjectNode();
            eachNode.put(CUSTOM_EVENT_TYPE_NAME, customEvent.getCustomeEventType().getName());
            eachNode.put(CUSTOM_EVENT_TYPE_CODE, customEvent.getCustomeEventType().toString());
            eachNode.put(CUSTOM_EVENT_EXECUTION_STRATEGY_NAME, customEvent.getExecutionStrategy().getName());
            eachNode.put(CUSTOM_EVENT_EXECUTION_STRATEGY_CODE, customEvent.getExecutionStrategy().toString());
            eachNode.put(CUSTOM_EVENT_ASSIGNMENT_FIELD_CONFIGURATION, customEvent.getAssignmentFieldConfiguration());
            eachNode.put(CUSTOM_EVENT_SERVICE_NAME, customEvent.getServiceName());
            eachNode.put(CUSTOM_EVENT_METHOD, customEvent.getMethod());
            eachNode.put(CUSTOM_EVENT_EXISTENCEPARAMETER, customEvent.getExistenceParameter());
            processCustomEventListArrayNode.add(eachNode);
        }
        propertiesNode.set(PROPERTY_PROCESS_CUSTOM_EVENT_LISTENERS_CONFIG, processCustomEventListArrayNode);
    }

    /**
     * 自定义事件
     *
     * @param elementNode node
     * @param userTask    task
     */
    private void parseJsonToCustomEventListeners(JsonNode elementNode, KaiteBaseUserTask userTask) {
        List<CustomEvent> customEventListeners = new ArrayList<>();
        ArrayNode eventNodes = (ArrayNode) elementNode.get(PROPERTY_PROCESS_CUSTOM_EVENT_LISTENERS_CONFIG);
        if (eventNodes == null) {
            return;
        }
        for (JsonNode eventNode : eventNodes) {
            CustomEvent customEvent = new CustomEvent();
            customEvent.setType(CustomEvent.CustomEventEnum.getEventByCode(getValueAsString(CUSTOM_EVENT_TYPE_CODE, eventNode)));
            customEvent.setExecutionStrategy(CustomEvent.CustomExecutionStrategyEnum.getExecutionStrategyByCode(getValueAsString(CUSTOM_EVENT_EXECUTION_STRATEGY_CODE, eventNode)));
            customEvent.setAssignmentFieldConfiguration(getValueAsString(CUSTOM_EVENT_ASSIGNMENT_FIELD_CONFIGURATION, eventNode));
            customEvent.setServiceName(getValueAsString(CUSTOM_EVENT_SERVICE_NAME, eventNode));
            customEvent.setMethod(getValueAsString(CUSTOM_EVENT_METHOD, eventNode));
            customEvent.setExistenceParameter(getValueAsBoolean(CUSTOM_EVENT_EXISTENCEPARAMETER, eventNode));
            customEventListeners.add(customEvent);
        }
        userTask.setCustomEventListeners(customEventListeners);
    }

    /**
     * 任务按钮解析
     *
     * @param elementNode jsonNode信息
     * @param task        task
     */
    protected void parseUserTaskJsonToButtonConfig(JsonNode elementNode, KaiteBaseUserTask task, Map<String, JsonNode> shapeMap) {
        ArrayNode taskButtonArrayNode = (ArrayNode) elementNode.get(PROPERTY_BUTTONS_CONFIG);
        List<TaskButton> buttons = task.getButtons().getButtons();
        ArrayNode arrayNode = (ArrayNode) shapeMap.get(STENCIL_SUB_PROCESS).get(EDITOR_SHAPE_PROPERTIES).get(PROPERTY_PROCESS_BUTTON_CONFIG);
        for (JsonNode eachNode : arrayNode) {
            for (Button taskButton : buttons) {
                if (taskButton.getCode().equalsIgnoreCase(getValueAsString(PROPERTY_BUTTON_CODE, eachNode))) {
                    taskButton.setBackendListeners(getValueAsString(PROPERTY_BUTTON_BACKEND_LISTENERS, eachNode));
                    taskButton.setPcListeners(getValueAsString(PROPERTY_BUTTON_PC_LISTENERS, eachNode));
                    taskButton.setAppListeners(getValueAsString(PROPERTY_BUTTON_APP_LISTENERS, eachNode));
                    taskButton.setCustomizeName(getValueAsString(PROPERTY_BUTTON_CUSTOMIZE_NAME, eachNode));
                    taskButton.setCustomizeComments(getValueAsString(PROPERTY_BUTTON_CUSTOMIZE_COMMENTS, eachNode));
                }
            }
        }

        for (JsonNode eachNode : taskButtonArrayNode) {
            for (Button taskButton : buttons) {
                if (taskButton.getCode().equalsIgnoreCase(getValueAsString(PROPERTY_BUTTON_CODE, eachNode))) {
                    taskButton.setBackendListeners(getValueAsString(PROPERTY_BUTTON_BACKEND_LISTENERS, eachNode));
                    taskButton.setPcListeners(getValueAsString(PROPERTY_BUTTON_PC_LISTENERS, eachNode));
                    taskButton.setAppListeners(getValueAsString(PROPERTY_BUTTON_APP_LISTENERS, eachNode));
                    taskButton.setCustomizeName(getValueAsString(PROPERTY_BUTTON_CUSTOMIZE_NAME, eachNode));
                    taskButton.setCustomizeComments(getValueAsString(PROPERTY_BUTTON_CUSTOMIZE_COMMENTS, eachNode));
                }
            }
        }
    }

    /**
     * 任务驳回配置
     *
     * @return void
     */
    protected void parseDismissConfigToJson(KaiteBaseUserTask userTask, ObjectNode flowElementNode) {
        ObjectNode taskDismissNode = objectMapper.createObjectNode();
        if (userTask.getTaskDismissConfig() == null) {
            return;
        }
        TaskDismissConfigImpl taskDismissConfig = userTask.getTaskDismissConfig();
        taskDismissNode.put(PROPERTY_ENABLE, convertBooleanToIntJson(taskDismissConfig.isEnable()));
        taskDismissNode.put(PROPERTY_USERTASK_DISMISS_TASKID, taskDismissConfig.getDismissTaskId());
        ArrayNode userTaskCommentArray = objectMapper.createArrayNode();
        for (TaskDismissBreakdownButton taskButton : taskDismissConfig.getCommitBreakdown()) {
            ObjectNode eachButtonNode = objectMapper.createObjectNode();
            eachButtonNode.put(PROPERTY_TASK_COMMIT_BREAKDOWN_BUTTON_NAME, taskButton.getName());
            eachButtonNode.put(PROPERTY_TASK_COMMIT_BREAKDOWN_NODE_ID, taskButton.getNodeId());
            eachButtonNode.put(PROPERTY_TASK_COMMIT_BREAKDOWN_NODE_NAME, taskButton.getName());
            userTaskCommentArray.add(eachButtonNode);
        }
        taskDismissNode.set(PROPERTY_USERTASK_DISMISS_COMMIT_BREAKDOWN_CONFIG, userTaskCommentArray);
        taskDismissNode.put(PROPERTY_USERTASK_DISMISS_ENABLEDIRECTSEND, convertBooleanToIntJson(taskDismissConfig.getDirectSendAfterReturn()));
        taskDismissNode.put(PROPERTY_USERTASK_DISMISS_FORCECOMMITAFTERDISMISS, convertBooleanToIntJson(taskDismissConfig.isForceCommitAfterDismiss()));
        taskDismissNode.put(PROPERTY_USERTASK_DISMISS_DISABLESENDAFTERDISMISS, convertBooleanToIntJson(taskDismissConfig.getDisableSendAfterDismiss()));
        taskDismissNode.put(PROPERTY_USERTASK_DISMISS_NORETURN, convertBooleanToIntJson(taskDismissConfig.getNoReturn()));
        taskDismissNode.put(PROPERTY_USERTASK_DISMISS_DIRECTSENDAFTERRETURN, convertBooleanToIntJson(taskDismissConfig.getDirectSendAfterReturn()));
        flowElementNode.set(PROPERTY_USERTASK_DISMISS_CONFIG, taskDismissNode);
    }


    /**
     * 驳回
     *
     * @param elementNode node
     * @param userTask    task
     */
    private void parseJsonToTaskDismissConfig(JsonNode elementNode, KaiteBaseUserTask userTask) {
        JsonNode jsonNode = elementNode.get(PROPERTY_USERTASK_DISMISS_CONFIG);
        if (jsonNode == null) {
            return;
        }
        TaskDismissConfigImpl taskDismissConfig = new TaskDismissConfigImpl();
        taskDismissConfig.setEnable(getValueAsBoolean(UNIVERSAL_ENABLE, jsonNode));
        try {
            ArrayNode arrayNode = (ArrayNode) jsonNode.get(PROPERTY_USERTASK_DISMISS_TASKID);
            List<String> ayyayNodeIds = new ArrayList<>();
            for (JsonNode jsonNode1 : arrayNode) {
                ayyayNodeIds.add(jsonNode1.asText());
            }
            taskDismissConfig.setDismissTaskId(ayyayNodeIds.stream().collect(Collectors.joining(",")));
        } catch (Exception e) {
            taskDismissConfig.setDismissTaskId("");
        }
        List<TaskDismissBreakdownButton> commitBreakdown = new ArrayList<>();
        if (jsonNode.get(PROPERTY_TASK_COMMIT_BREAKDOWN_CONFIG) != null) {
            ArrayNode arrayNode = (ArrayNode) jsonNode.get(PROPERTY_TASK_COMMIT_BREAKDOWN_CONFIG);
            if (arrayNode != null) {
                for (JsonNode button : arrayNode) {
                    TaskDismissBreakdownButton taskDismissBreakdownButton = new TaskDismissBreakdownButton();
                    taskDismissBreakdownButton.setName(getValueAsString(PROPERTY_TASK_COMMIT_BREAKDOWN_BUTTON_NAME, button));
                    taskDismissBreakdownButton.setNodeId(getValueAsString(PROPERTY_TASK_COMMIT_BREAKDOWN_NODE_ID, button));
                    taskDismissBreakdownButton.setNodeName(getValueAsString(PROPERTY_TASK_COMMIT_BREAKDOWN_NODE_NAME, button));
                    commitBreakdown.add(taskDismissBreakdownButton);
                }
            }
        }
        taskDismissConfig.setCommitBreakdown(commitBreakdown);
        taskDismissConfig.setDirectSendAfterDismiss(getValueAsBoolean(PROPERTY_USERTASK_DISMISS_ENABLEDIRECTSEND, jsonNode));
        taskDismissConfig.setForceCommitAfterDismiss(getValueAsBoolean(PROPERTY_USERTASK_DISMISS_FORCECOMMITAFTERDISMISS, jsonNode));
        taskDismissConfig.setDisableSendAfterDismiss(getValueAsBoolean(PROPERTY_USERTASK_DISMISS_DISABLESENDAFTERDISMISS, jsonNode));
        taskDismissConfig.setNoReturn(getValueAsBoolean(PROPERTY_USERTASK_DISMISS_NORETURN, jsonNode));
        taskDismissConfig.setDirectSendAfterReturn(getValueAsBoolean(PROPERTY_USERTASK_DISMISS_DIRECTSENDAFTERRETURN, jsonNode));
        userTask.setTaskDismissConfig(taskDismissConfig);
    }


    /**
     * 传阅配置
     *
     * @return void
     */
    protected void parseTaskPassRoundConfigToJson(KaiteBaseUserTask userTask, ObjectNode flowElementNode) {
        ObjectNode taskPassroundNode = objectMapper.createObjectNode();
        TaskPassRoundConfigImpl taskPassRoundConfig = userTask.getTaskPassRoundConfig();
        ArrayNode sourceArray = objectMapper.createArrayNode();
        List<PassRoundResource> list = taskPassRoundConfig.getPassRoundResourceList();
        for (PassRoundResource passRoundResource : list) {
            sourceArray.add(fillPassUserConfigToJson(passRoundResource));
        }
        taskPassroundNode.put(UNIVERSAL_ENABLE, convertBooleanToIntJson(taskPassRoundConfig.isEnable()));
        taskPassroundNode.put(PROPERTY_USERTASK_PASSROUND_AUTO, convertBooleanToIntJson(taskPassRoundConfig.isAuto()));
        taskPassroundNode.set(PROPERTY_USERTASK_PASSROUND_CIRCULATIONRULES_CONFIG, sourceArray);
        flowElementNode.set(PROPERTY_USERTASK_PASSROUND_CONFIG, taskPassroundNode);
    }

    /**
     * 传阅
     *
     * @param elementNode node
     * @param userTask    task
     */
    private void parseJsonToTaskPassRoundConfig(JsonNode elementNode, KaiteBaseUserTask userTask) {
        TaskPassRoundConfigImpl taskPassRoundConfig = new TaskPassRoundConfigImpl();
        JsonNode jsonNode = elementNode.get(PROPERTY_USERTASK_PASSROUND_CONFIG);
        taskPassRoundConfig.setEnable(getValueAsBoolean(UNIVERSAL_ENABLE, jsonNode));
        taskPassRoundConfig.setAuto(getValueAsBoolean(PROPERTY_USERTASK_PASSROUND_AUTO, jsonNode));
        ArrayNode circulationRulesNode = (ArrayNode) jsonNode.get(PROPERTY_USERTASK_PASSROUND_CIRCULATIONRULES_CONFIG);
        for (JsonNode circulationRule : circulationRulesNode) {
            PassRoundResource passRoundResource = new PassRoundResource();
            if (PassRoundResource.PassRoundTypeEnum.getType(getValueAsString(PROPERTY_USERTASK_PASSROUND_CIRCULATIONRULES_CODE, circulationRule)) == null) {
                continue;
            }
            passRoundResource.setPassRoundTypeEnum(PassRoundResource.PassRoundTypeEnum.getType(getValueAsString(PROPERTY_USERTASK_PASSROUND_CIRCULATIONRULES_CODE, circulationRule)));
            if (passRoundResource.getPassRoundTypeEnum().equals(PassRoundResource.PassRoundTypeEnum.customConfig)) {
                passRoundResource.setService(getValueAsString(PROPERTY_ASSIGNMENT_CUSTOM_SERVICENAME, circulationRule));
                passRoundResource.setMethod(getValueAsString(PROPERTY_ASSIGNMENT_CUSTOM_METHODNAME, circulationRule));
            } else {
                passRoundResource.setResourceId(getValueAsString(PASS_ROUND_ID, circulationRule));
                passRoundResource.setResourceName(getValueAsString(UNIVERSAL_NAME, circulationRule));
            }
            taskPassRoundConfig.addPassRoundResource(passRoundResource);
        }
        userTask.setTaskPassRoundConfig(taskPassRoundConfig);
    }


    private ObjectNode fillPassUserConfigToJson(PassRoundResource passRoundResource) {
        ObjectNode eachNode = objectMapper.createObjectNode();
        eachNode.put(PROPERTY_USERTASK_PASSROUND_CIRCULATIONRULES_CODE, passRoundResource.getPassRoundTypeEnum().toString());
        eachNode.put(PROPERTY_USERTASK_PASSROUND_CIRCULATIONRULES_NAME, passRoundResource.getPassRoundTypeEnum().getName());

        if (passRoundResource.getPassRoundTypeEnum().equals(PassRoundResource.PassRoundTypeEnum.customerDepartmentConfig) ||
                passRoundResource.getPassRoundTypeEnum().equals(PassRoundResource.PassRoundTypeEnum.starterUser)) {
            return eachNode;
        }

        if (passRoundResource.getPassRoundTypeEnum().equals(PassRoundResource.PassRoundTypeEnum.departmentConfig) ||
                passRoundResource.getPassRoundTypeEnum().equals(PassRoundResource.PassRoundTypeEnum.roleConfig) ||
                passRoundResource.getPassRoundTypeEnum().equals(PassRoundResource.PassRoundTypeEnum.userConfig) ||
                passRoundResource.getPassRoundTypeEnum().equals(PassRoundResource.PassRoundTypeEnum.formFieldConfig)) {
            eachNode.put(UNIVERSAL_ID, passRoundResource.getResourceId());
            eachNode.put(UNIVERSAL_NAME, passRoundResource.getResourceName());
        }

        if (passRoundResource.getPassRoundTypeEnum().equals(PassRoundResource.PassRoundTypeEnum.customConfig)) {
            eachNode.put(UNIVERSAL_ID, passRoundResource.getService());
            eachNode.put(UNIVERSAL_ID, passRoundResource.getMethod());
        }
        return eachNode;
    }


    protected void convertJsonToElement(JsonNode elementNode, KaiteBaseUserTask userTask, Map<String, JsonNode> shapeMap) {
        parseJsonToCommitBreakdownButtonList(elementNode, userTask);
        parseJsonToTaskDismissConfig(elementNode, userTask);
        parseJsonToTaskEarlyWarningAndPostponementConfig(elementNode, userTask);
        parseJsonToTaskPassRoundConfig(elementNode, userTask);
        parseJsonToCustomEventListeners(elementNode, userTask);
        parseJsonToAddSignatureConfig(elementNode, userTask);
        parseJsonToTaskApprovalNoticeConfig(elementNode, userTask);
        parseJsonToTaskFormBasicConfig(elementNode, userTask);
        parseUserTaskJsonToButtonConfig(elementNode, userTask, shapeMap);
        super.convertJsonToElement(elementNode, userTask);
    }

}
